home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Resources / Online / Miami / MiamiSDK / examples / ttcptest.c < prev   
C/C++ Source or Header  |  1997-12-28  |  5KB  |  223 lines

  1. /*
  2.  * ttcptest.c
  3.  *
  4.  * Small example for a T/TCP-compliant client.
  5.  *
  6.  * This client tries to connect to the auth (identd) port of the
  7.  * specified host using T/TCP. If T/TCP is not supported it falls
  8.  * back to TCP.
  9.  *
  10.  * (C) Copyright 1996,1997 by Nordic Global Inc. All rights reserved.
  11.  * T/TCP code for use with Miami only.
  12.  *
  13.  * 07/30/97: first version
  14.  *
  15.  * 12/28/97: - added support for PPC
  16.  *           - added support for protocol-independent hostname lookup
  17.  *             (for IPv6 compatibility)
  18.  */
  19.  
  20. #define __USE_SYSBASE
  21. #include <proto/exec.h>
  22. #include <proto/miami.h>
  23. #include <proto/socket.h>
  24.  
  25. #include <sys/socket.h>
  26. #include <netinet/tcp.h>
  27. #include <dos.h>
  28. #include <netdb.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <errno.h>
  33.  
  34.  
  35. struct Library *MiamiBase=0;
  36.  
  37. static int dottcp=0;
  38. static int protoind=0;
  39.  
  40. #define REQUEST "1 : 1\r\n"
  41.  
  42. void myexit(void) {
  43.     if(MiamiBase) {
  44.         CloseLibrary(MiamiBase);
  45.         MiamiBase=0;
  46.     }
  47. }
  48.  
  49. int mybreak(void) {
  50.     myexit();
  51.     return 1;
  52. }
  53.  
  54. void get_response(int sockfd,char *buf,int max) {
  55.     int len=0,le;
  56.     while(len<max-1) {
  57.         le=recv(sockfd,buf+len,max-len-1,0);
  58.         if(le==0) {
  59.             buf[len]=0;
  60.             return;
  61.         }
  62.         if(le<0) {
  63.             fprintf(stderr,"recv: error %d\n",Errno());
  64.             exit(10);
  65.         }
  66.         len+=le;
  67.     }
  68.     buf[max-1]=0;
  69. }    
  70.  
  71. void main(int argc,char **argv) {
  72.     struct hostent *he;
  73.     struct servent *se;
  74.     long sockfd,n=1,err,family,sockettype;
  75.     char buf[256];
  76.     struct sockaddr_in sin;
  77.     struct sockaddr *sa;
  78.     struct addrinfo *addrinfo=0;
  79.  
  80.     if(argc==0)
  81.         exit(0);
  82.     if(argc!=2) {
  83.         fprintf(stderr,"Usage: %s host\n",argv[0]);
  84.         exit(10);
  85.     }
  86.  
  87.     /* install exit and break hooks so MiamiBase gets closed
  88.        in all cases */
  89.  
  90.     atexit(myexit);
  91.  
  92. #ifndef __PPC__
  93.     /* onbreak() is not supported by SAS/C-PPC yet */
  94.     onbreak(mybreak);
  95. #endif
  96.  
  97.     /* miami.library versions >= 3 support T/TCP */
  98.  
  99.     if(MiamiBase=OpenLibrary("miami.library",3)) {
  100.         dottcp=1;
  101.         
  102.         /* miami.library versions >= 12 support protocol-
  103.            independent hostname lookup (IPv6 compatible) */
  104.  
  105.         if(MiamiBase->lib_Version>=12)
  106.             protoind=1;
  107.     }
  108.  
  109.  
  110.     /* ---- host name / service stuff */
  111.  
  112.     if(protoind) {
  113.     
  114.         /* new protocol-independent version */
  115.  
  116.         if(getaddrinfo(argv[1],"auth",0,&addrinfo)) {
  117.             fprintf(stderr,"Host `%s' with service `auth' not found\n",argv[1]);
  118.             exit(10);
  119.         }
  120.         family=addrinfo->ai_family;
  121.         sockettype=addrinfo->ai_socktype;
  122.         sa=addrinfo->ai_addr;
  123.     } else {        
  124.  
  125.         /* old IPv4-only version */
  126.  
  127.         if(!(he=gethostbyname(argv[1]))) {
  128.             fprintf(stderr,"Host `%s' not found\n",argv[1]);
  129.             exit(10);
  130.         }
  131.         if(!(se=getservbyname("auth","tcp"))) {
  132.             fprintf(stderr,"Service `auth' not found\n");
  133.             exit(10);
  134.         }
  135.         sin.sin_family=family=AF_INET;
  136.         sockettype=SOCK_STREAM;
  137.         sin.sin_len=sizeof(sin);
  138.         memcpy(&sin.sin_addr,he->h_addr,he->h_length);
  139.         sin.sin_port=se->s_port;
  140.         sa=(struct sockaddr *)&sin;
  141.     }
  142.  
  143.     if(0>(sockfd=socket(family,sockettype,0))) {
  144.         fprintf(stderr,"Unable to create socket\n");
  145.         exit(10);
  146.     }
  147.  
  148.     /* ---- start of T/TCP stuff */
  149.     if(dottcp) {
  150.  
  151.         /* The following call is useful if a sendto() may be larger than
  152.            the MSS, to ensure that packets are packed tightly. (If this seems
  153.            strange, that's probably because it is. It has to do with some
  154.            odd quirks in the implementation of sosend() in all BSD-derived
  155.            TCP/IP stacks. Don't ask any questions -- just add this call
  156.            to your program :-)).
  157.  
  158.            HOWEVER: only add the call if you do NOT reuse your TCP connection
  159.            for multiple requests. If you want to transmit multiple pairs of
  160.            "transaction"/"response" across the same TCP link (e.g. HTTP 1.1
  161.            "persistent TCP connections"), then do NOT add the following
  162.            call. */
  163.  
  164.         setsockopt(sockfd,IPPROTO_TCP,TCP_NOPUSH,(char *)&n,sizeof(n));
  165.  
  166.         
  167.         /* Instead of the usual connect() followed by send(), for T/TCP you
  168.            use a sendto() call, as you would for UDP sockets.
  169.            
  170.            If you have a known amount of data to send that you can send in
  171.            a single function call, then you should use one single sendto()
  172.            call with the MSG_EOF flag set, as in this example. This is the
  173.            preferred way to do it, and gives best performance.
  174.  
  175.            If you absolutely need to loop then use a sequence like
  176.  
  177.             sendto(,,,0,,);
  178.             while(!done) {
  179.              send(,,,0);
  180.             }
  181.             send(,,,MSG_EOF);
  182.  
  183.            this means set the MSG_EOF flag in the *last* send() call only.
  184.  
  185.            MSG_EOF performs an implicit shutdown() for one direction of the
  186.            link, improving performance because the shutdown() can be
  187.            piggy-backed on data packets, i.e. no additional packets are
  188.            needed for a shutdown() or CloseSocket() later.
  189.            
  190.            However *do not* use MSG_EOF if you want to re-use your
  191.            connection for subsequent requests (e.g. "persistent TCP
  192.            connections" in HTTP-1.1). */
  193.  
  194.         if(sendto(sockfd,REQUEST,strlen(REQUEST),MSG_EOF,sa,sa->sa_len)
  195.          !=strlen(REQUEST)) {
  196.             if((err=Errno())==ENOTCONN) {
  197.                  /* T/TCP failed. Try ordinary TCP */
  198.                 dottcp=0;
  199.             } else {
  200.                 fprintf(stderr,"sendto: error %d\n",err);
  201.                 exit(10);
  202.             }
  203.         }
  204.     }
  205.     /* ---- end of T/TCP stuff */
  206.     
  207.     if(!dottcp) {
  208.         if(connect(sockfd,sa,sa->sa_len)<0) {
  209.             fprintf(stderr,"connect: error %d\n",Errno());
  210.             exit(10);
  211.         }
  212.         if(send(sockfd,REQUEST,strlen(REQUEST),0)!=strlen(REQUEST)) {
  213.             fprintf(stderr,"send: error %d\n",Errno());
  214.             exit(10);
  215.         }
  216.     }
  217.     get_response(sockfd,buf,256);
  218.     puts(buf);
  219.     CloseSocket(sockfd);
  220.     if(addrinfo)
  221.         freeaddrinfo(addrinfo);
  222. }
  223.